package com.springspirit.monitor.web;

import java.io.IOException;
import java.util.Queue;
import java.util.Random;
import java.util.concurrent.ConcurrentLinkedQueue;

import javax.servlet.AsyncContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.codehaus.jettison.json.JSONArray;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

import com.springspirit.framework.message.LogMessage;
import com.springspirit.monitor.EventAggregator;

/**
 * 
 * @author greatshin
 *
 */
public final class LogViewerServlet extends HttpServlet {

	private static final long serialVersionUID = -7328847247659890805L;
	
	private static final Logger logger = LoggerFactory.getLogger(LogViewerServlet.class);

	private final Queue<AsyncContext> asyncContexts = new ConcurrentLinkedQueue<AsyncContext>();
	
	private final Random random = new Random();
	    
	private final Thread generator = new Thread("Event generator") {
		@Override
		public void run() {
			
			if(logger.isDebugEnabled()){
				logger.debug("LogViewerServlet generator running...");
			}
			
			while (!Thread.currentThread().isInterrupted()) {
				try {
//					Thread.sleep(random.nextInt(500));
					 Thread.sleep(500l);
					
					if(logger.isDebugEnabled()){
						if(!asyncContexts.isEmpty()){
							logger.debug("AsyncContexts is not empty...");
						}else{
							logger.debug("AsyncContexts is empty...");
						}
					}
					
					while (!asyncContexts.isEmpty()) {
						AsyncContext asyncContext = asyncContexts.poll();
						HttpServletResponse peer = (HttpServletResponse) asyncContext.getResponse();
						
						LogMessage logMessage = (LogMessage)getEventAggregator().receiveJmsMessage();
						
//						JSONArray jSONArray = new JSONArray().put("At " + new Date());
						JSONArray jSONArray = new JSONArray().put(logMessage.toMap());

						if(logger.isDebugEnabled()){
							logger.debug("LogViewerServlet JSONArray ... " + jSONArray.toString());
						}

						peer.getWriter().write(jSONArray.toString());
						peer.setStatus(HttpServletResponse.SC_OK);
						peer.setContentType("application/json");
						asyncContext.complete();
					}
				} catch (InterruptedException e) {
					
//					if(logger.isDebugEnabled()){
//						logger.debug("EventPublisherServlet thread run() Interrpted..." + e.getMessage());
//					}
					
					Thread.currentThread().interrupt();
				} catch (IOException e) {
					throw new RuntimeException(e.getMessage(), e);
				}
			}
		}
	};

	@Override
	public void init() throws ServletException {
		
		if(logger.isDebugEnabled()){
			logger.debug("LogViewerServlet initialized...");
		}
		
		generator.start();
	}

	@Override
	public void destroy() {
		
		if(logger.isDebugEnabled()){
			logger.debug("LogViewerServlet destroyed...");
		}
		
		generator.interrupt();
	}

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		AsyncContext asyncContext = req.startAsync();
		asyncContext.setTimeout(0);
		
		if(logger.isDebugEnabled()){
			logger.debug("An AsyncContext Queued...");
		}
		
		asyncContexts.offer(asyncContext);
	}
	
	private EventAggregator getEventAggregator(){
		WebApplicationContext wac = WebApplicationContextUtils.getWebApplicationContext(getServletContext());				    
	    return (EventAggregator)wac.getBean("eventAggregator"); 
	}
}
